android新版本(8.0以上)使用Toast的那些坑

您所在的位置:网站首页 华为nova5i pro短信通知不弹出 android新版本(8.0以上)使用Toast的那些坑

android新版本(8.0以上)使用Toast的那些坑

2023-04-22 19:50| 来源: 网络整理| 查看: 265

华为、三星等机型禁用通知权限后Toast不弹出 原因

查看Toast源码后发现,Toast显示要通过INotificationManager类来实现,而当通知禁用后,调用此类会返回异常,所以导致通知不显示,源码如下:

public void show() { if (mNextView == null) { throw new RuntimeException("setView must have been called"); } INotificationManager service = getService(); String pkg = mContext.getOpPackageName(); TN tn = mTN; tn.mNextView = mNextView; try { service.enqueueToast(pkg, tn, mDuration); } catch (RemoteException e) { // 权限禁用后走这里,这里是空方法,所以会发生既不crash又无响应的情况 } }

这是一个google的bug,部分小米手机重写了Toast代码,所以可以正常执行,我们可以通过反射的方式来暴力绕过,也就有了如下解决方式:

解决方法 public class ToastUtils { private static Object iNotificationManagerObj; /** * @param context * @param message */ public static void show(Context context, String message) { show(context.getApplicationContext(), message, Toast.LENGTH_SHORT); } /** * @param context * @param message */ public static void show(Context context, String message, int duration) { if (TextUtils.isEmpty(message)) { return; } //后setText 兼容小米默认会显示app名称的问题 Toast toast = Toast.makeText(context, null, duration); toast.setText(message); if (isNotificationEnabled(context)) { toast.show(); } else { showSystemToast(toast); } } /** * 显示系统Toast */ private static void showSystemToast(Toast toast) { try { Method getServiceMethod = Toast.class.getDeclaredMethod("getService"); getServiceMethod.setAccessible(true); //hook INotificationManager if (iNotificationManagerObj == null) { iNotificationManagerObj = getServiceMethod.invoke(null); Class iNotificationManagerCls = Class.forName("android.app.INotificationManager"); Object iNotificationManagerProxy = Proxy.newProxyInstance(toast.getClass().getClassLoader(), new Class[]{iNotificationManagerCls}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //强制使用系统Toast if ("enqueueToast".equals(method.getName()) || "enqueueToastEx".equals(method.getName())) { //华为p20 pro上为enqueueToastEx args[0] = "android"; } return method.invoke(iNotificationManagerObj, args); } }); Field sServiceFiled = Toast.class.getDeclaredField("sService"); sServiceFiled.setAccessible(true); sServiceFiled.set(null, iNotificationManagerProxy); } toast.show(); } catch (Exception e) { e.printStackTrace(); } } /** * 消息通知是否开启 * * @return */ private static boolean isNotificationEnabled(Context context) { NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context); boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled(); return areNotificationsEnabled; } } 内容相同Toast短时间不能重复弹出 原因

当我们重复点击Toast时候,会连续弹出很多Toast,视觉体验不好,于是网上流传着这些解决方法:

Toast mToast; public void showToast(String text) { if (mToast == null) { mToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT); } else { mToast.setText(text); mToast.setDuration(Toast.LENGTH_SHORT); } mToast.show(); }

这个方法在旧版本android上没有问题,新版本当短时间显示同一个Toast时,会显示不出来。

文字相同且当前Toast正在显示时,系统会认为是误触操作,从而屏蔽当前显示Toast请求。

出现这个问题据说是为了防止某些流氓app一直弹出一个模仿系统界面的Toast从而导致系统瘫痪。

解决方法

这是系统的限制,想要绕过这个限制只能自定义Toast了,这里我推荐git上的大神自定义版Toast——XToast



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3